from flask import Flask, request, make_response, render_template, jsonify
import pandas as pd
import json
import os
import numpy as np

# 导入main.py中的函数
from main import find_min_cycle_and_mirror, compare_cycles_between_ids, find_similar_cycles

app = Flask(__name__)

# 全局变量，用于存储数据
df = None

# 初始化函数，加载Excel数据
def init_data():
    global df
    try:
        # 获取当前文件所在目录
        current_dir = os.path.dirname(os.path.abspath(__file__))
        # 构建Excel文件路径
        excel_path = os.path.join(current_dir, "..", "蒙皮属性库.xlsx")
        df = pd.read_excel(excel_path)
        df = df.set_index('ID')
        print(f"数据加载成功，共 {len(df)} 条记录")
    except Exception as e:
        print(f"数据加载失败: {e}")
        # 创建一个示例数据用于测试
        sample_data = {
            'ID': [1, 2, 3, 11421],
            'PLY1': [1.0, 2.0, 1.0, 5.0],
            'PLY2': [2.0, 3.0, 2.0, 6.0],
            'PLY3': [3.0, 4.0, 3.0, 7.0],
            'PLY4': [0.0, 0.0, 0.0, 8.0],
            'PLY5': [np.nan, np.nan, np.nan, np.nan],  # 添加NaN值用于测试
            'PLY6': [np.nan, np.nan, np.nan, np.nan]
        }
        df = pd.DataFrame(sample_data)
        df = df.set_index('ID')
        print("已创建示例数据")

# 处理NaN值的函数
def convert_nan_to_null(obj):
    """将对象中的NaN、Infinity、-Infinity转换为None（JSON中的null）"""
    if isinstance(obj, float):
        # 处理NaN和无穷值
        if pd.isna(obj) or obj == float('inf') or obj == float('-inf'):
            return None
        return obj
    elif isinstance(obj, dict):
        return {k: convert_nan_to_null(v) for k, v in obj.items()}
    elif isinstance(obj, list):
        return [convert_nan_to_null(item) for item in obj]
    elif isinstance(obj, pd.Series):
        return convert_nan_to_null(obj.to_dict())
    else:
        return obj

# 计算最大有效层数的函数
def calculate_max_effective_layers(id_data, id_val=None):
    """计算一个ID的最大有效层数
       - 首先尝试从ID值中提取层数信息
       - 如果无法从ID提取，则计算实际数据中的有效层数
    """
    # 1. 尝试从ID值中提取层数信息
    if id_val is not None:
        id_str = str(id_val)
        
        # 策略1: 检查ID是否符合特定模式（例如'11421'表示114层）
        # 对于ID长度为5位的情况，前三位是层数
        if len(id_str) >= 3:
            try:
                # 提取前1-3位作为潜在层数
                for i in range(min(3, len(id_str)), 0, -1):
                    potential_layers = int(id_str[:i])
                    # 验证：层数应该是合理的数字（1-200之间）
                    if 1 <= potential_layers <= 200:
                        return potential_layers
            except ValueError:
                pass
    
    # 2. 如果无法从ID提取，则检查实际数据中的最大PLY值
    # 过滤出PLY列
    ply_columns = [k for k in id_data.keys() if isinstance(k, str) and k.startswith('PLY')]
    
    if not ply_columns:
        return 0
    
    # 计算PLY列中的最大数值索引
    max_ply_number = 0
    for col in ply_columns:
        # 提取PLY后面的数字
        ply_number_str = col[3:]
        if ply_number_str.isdigit():
            ply_number = int(ply_number_str)
            max_ply_number = max(max_ply_number, ply_number)
    
    # 3. 最后，使用原始的连续序列计算方法作为后备
    # 过滤掉以'ID'开头的列，专注于PLY列
    ply_data = {k: v for k, v in id_data.items() if isinstance(k, str) and k.startswith('PLY')}
    
    # 计算不为null且不为0的数据的最大连续序列
    max_continuous = 0
    current_continuous = 0
    
    # 按照PLY后面的数字排序
    sorted_ply_keys = sorted(ply_data.keys(), key=lambda x: int(x[3:]) if x[3:].isdigit() else 0)
    
    for key in sorted_ply_keys:
        # 检查值是否不为null且不为0
        if ply_data[key] is not None and not pd.isna(ply_data[key]) and ply_data[key] != 0:
            current_continuous += 1
            max_continuous = max(max_continuous, current_continuous)
        else:
            current_continuous = 0
    
    # 返回三种方法中的最大值
    return max(max_ply_number, max_continuous)

# 获取达到最大有效层数的PLY数据
def get_ply_data_up_to_max_layers(id_data, max_layers):
    """获取达到最大有效层数的PLY数据"""
    # 过滤出PLY列并按数字排序
    ply_data = {k: v for k, v in id_data.items() if isinstance(k, str) and k.startswith('PLY')}
    sorted_ply_keys = sorted(ply_data.keys(), key=lambda x: int(x[3:]) if x[3:].isdigit() else 0)
    
    # 创建一个新的数据字典，只包含达到最大有效层数的PLY数据
    result = {}
    layer_count = 0
    
    for key in sorted_ply_keys:
        # 如果值不为null且不为0，则计入层数
        if ply_data[key] is not None and not pd.isna(ply_data[key]) and ply_data[key] != 0:
            layer_count += 1
        
        # 添加此PLY数据到结果中
        result[key] = ply_data[key]
        
        # 如果已达到最大有效层数，则停止添加
        if layer_count >= max_layers:
            break
    
    return result

# 在应用启动时初始化数据
init_data()

@app.route('/')
def index():
    return render_template('index.html')
    
@app.route('/test')
def tesst():
    return 'successed'

@app.route('/greet/<name>')
def greet(name):
    return f'Hello, {name}!'

@app.route('/submit', methods=['POST'])
def submit():
    username = request.form.get('username')
    return f'Hello, {username}!'

@app.route('/custom_response')
def custom_response():
    response = make_response('This is a custom response!')
    response.headers['X-Custom-Header'] = 'Value'
    return response

@app.route('/hello/<name>')
def hello(name):
    return render_template('hello.html', name=name)

# 新的API路由：查询ID属性
@app.route('/query')
def query_id():
    global df
    try:
        id_val = int(request.args.get('id'))
        if id_val not in df.index:
            return jsonify({'error': f'错误：ID {id_val} 不存在于数据中', 'available_ids': list(df.index)[:10]})
        
        # 获取数据
        id_data = df.loc[id_val]
        raw_data = id_data.to_dict()
        
        # 处理NaN值
        data = convert_nan_to_null(raw_data)
        
        # 计算最大有效层数，传入ID值
        max_effective_layers = calculate_max_effective_layers(data, id_val)
        
        # 获取达到最大有效层数的PLY数据
        ply_data = get_ply_data_up_to_max_layers(data, max_effective_layers)
        
        # 查找循环单元
        cycle_unit, mirror_unit, repeat_count = find_min_cycle_and_mirror(id_data.tolist())
        
        # 处理循环单元中的NaN值
        cycle_unit = convert_nan_to_null(cycle_unit)
        mirror_unit = convert_nan_to_null(mirror_unit)
        
        return jsonify({
            'id': id_val,
            'data': data,
            'ply_data': ply_data,  # 只包含达到最大有效层数的PLY数据
            'cycle_unit': cycle_unit,
            'mirror_unit': mirror_unit,
            'repeat_count': repeat_count,
            'max_effective_layers': max_effective_layers
        })
    except Exception as e:
        return jsonify({'error': f'查询失败: {str(e)}'})

# 新的API路由：比较两个ID
@app.route('/compare')
def compare_ids():
    global df
    try:
        id1 = int(request.args.get('id1'))
        id2 = int(request.args.get('id2'))
        
        # 检查ID是否存在
        if id1 not in df.index:
            return jsonify({'error': f'错误：ID {id1} 不存在'})
        if id2 not in df.index:
            return jsonify({'error': f'错误：ID {id2} 不存在'})
        
        # 获取两个ID的数据
        id_data1 = df.loc[id1]
        id_data2 = df.loc[id2]
        
        seq1 = id_data1.tolist()
        seq2 = id_data2.tolist()
        
        # 处理NaN值
        data1 = convert_nan_to_null(id_data1.to_dict())
        data2 = convert_nan_to_null(id_data2.to_dict())
        
        # 计算最大有效层数，传入ID值
        max_layers1 = calculate_max_effective_layers(data1, id1)
        max_layers2 = calculate_max_effective_layers(data2, id2)
        
        # 获取达到最大有效层数的PLY数据
        ply_data1 = get_ply_data_up_to_max_layers(data1, max_layers1)
        ply_data2 = get_ply_data_up_to_max_layers(data2, max_layers2)
        
        # 分别找到最小循环单元
        cycle1, _, _ = find_min_cycle_and_mirror(seq1)
        cycle2, _, _ = find_min_cycle_and_mirror(seq2)
        
        # 处理循环单元中的NaN值
        cycle1 = convert_nan_to_null(cycle1)
        cycle2 = convert_nan_to_null(cycle2)
        
        # 比较循环单元是否相同
        matches = cycle1 == cycle2
        
        return jsonify({
            'id1': id1,
            'id2': id2,
            'data1': data1,
            'data2': data2,
            'ply_data1': ply_data1,
            'ply_data2': ply_data2,
            'cycle1': cycle1,
            'cycle2': cycle2,
            'matches': matches,
            'max_effective_layers1': max_layers1,
            'max_effective_layers2': max_layers2
        })
    except Exception as e:
        return jsonify({'error': f'比较失败: {str(e)}'})

# 新的API路由：查找相似ID
@app.route('/similar')
def find_similar():
    global df
    try:
        target_id = int(request.args.get('id'))
        
        if target_id not in df.index:
            return jsonify({'error': f'错误：ID {target_id} 不存在'})
        
        # 获取目标ID的数据
        target_data = df.loc[target_id]
        target_seq = target_data.tolist()
        
        # 处理NaN值
        data = convert_nan_to_null(target_data.to_dict())
        
        # 计算最大有效层数，传入ID值
        max_effective_layers = calculate_max_effective_layers(data, target_id)
        
        # 获取达到最大有效层数的PLY数据
        ply_data = get_ply_data_up_to_max_layers(data, max_effective_layers)
        
        # 获取目标ID的循环单元
        target_cycle, _, _ = find_min_cycle_and_mirror(target_seq)
        
        # 处理循环单元中的NaN值
        target_cycle = convert_nan_to_null(target_cycle)
        
        # 查找所有具有相同循环单元的ID
        similar_ids = []
        
        for id_val in df.index:
            if id_val == target_id:
                continue
                
            try:
                seq = df.loc[id_val].tolist()
                cycle, _, _ = find_min_cycle_and_mirror(seq)
                
                # 处理循环单元中的NaN值
                cycle = convert_nan_to_null(cycle)
                
                if cycle == target_cycle:
                    similar_ids.append(id_val)
            except Exception as e:
                # 跳过处理出错的ID
                continue
        
        return jsonify({
            'target_id': target_id,
            'target_cycle': target_cycle,
            'similar_ids': similar_ids,
            'data': data,
            'ply_data': ply_data,
            'max_effective_layers': max_effective_layers
        })
    except Exception as e:
        return jsonify({'error': f'查找失败: {str(e)}'})

if __name__ == '__main__':
    app.run(debug=True)